import { useDrop } from "react-dnd";
import { DragItemType, DropIndicatorType } from "../utils/constant";
import { useContext } from "react";
import { RuleTreeContext, RuleTreePropsContext } from "./RuleTreeContext";
import { invokeFunc, toNamePath, wrapperCls } from "../utils";
import styled from "styled-components";
import { fieldNamesTreeMap } from "../utils/global";
import type { FieldNames } from "../types";
import { useOutterComponents } from "../utils/hooks";

export const WrapperDropIndicator = styled.div<{
  $backgroundColor: string;
  $canDrop: boolean;
}>`
  background-color: ${(props) => props.$backgroundColor};
  opacity: ${(props) => (props.$canDrop ? 1 : 0)};
`;

export default function DropIndicator(props: {
  children: React.ReactNode;
  index: number;
  levelPath: number[];
  overMaxCount?: boolean;
}) {
  const { prefixCls } = useContext(RuleTreeContext);
  const { uid, draggable, max } = useContext(RuleTreePropsContext);
  const cls = wrapperCls(prefixCls);
  const { children: ChildrenKey } = fieldNamesTreeMap.get(
    uid
  ) as Required<FieldNames>;
  const { Form } = useOutterComponents();
  const form = Form.useFormInstance();

  const [{ canDrop, isOver }, drop] = useDrop(
    () => ({
      accept: DragItemType,
      collect: (monitor) => {
        return {
          isOver: monitor.isOver(),
          canDrop: monitor.canDrop(),
        };
      },
      canDrop: (item: {
        dragLevelPath: string[];
        dragIndex: number;
        dragUid: string;
      }) => {
        if (props.overMaxCount) {
          const newPath = toNamePath(props.levelPath, ChildrenKey);
          const storeValue = form.getFieldsValue(newPath);
          // 处理当配置了max属性后，拖拽时不允许超过max属性
          if (
            storeValue.children.length >= max! &&
            item.dragLevelPath.join("-") !== props.levelPath.join("-")
          ) {
            return false;
          }
        }

        // 同一个组件实例内才允许拖放
        if (item.dragUid !== uid) {
          return false;
        }

        // 处理draggable为函数的情况
        if (
          typeof draggable === "function" &&
          !draggable({ levelPath: props.levelPath })
        ) {
          return false;
        }

        // 相同层级自身和自身下一个位置不能放置
        if (item.dragLevelPath.join("-") === props.levelPath.join("-")) {
          if (props.index === item.dragIndex) {
            return false;
          }

          if (props.index === item.dragIndex + 1) {
            return false;
          }
        } else {
          // 不同层级，不允许往自节点放置
          const dragNamePathStr = [...item.dragLevelPath, item.dragIndex].join(
            "-"
          );
          const namePathStr = [...props.levelPath, props.index].join("-");
          if (namePathStr.startsWith(dragNamePathStr)) {
            return false;
          }
        }

        return true;
      },
      drop: (item) => {
        return {
          ...item,
          from: DropIndicatorType,
          dropLevelPath: props.levelPath,
          dropIndex: props.index,
        };
      },
    }),
    [props.levelPath, props.index, props.overMaxCount, draggable, max, form]
  );

  const bgColor = invokeFunc(() => {
    if (isOver) {
      return canDrop ? "#1890ff" : "red";
    }
    return "#91d5ff";
  });

  return (
    <WrapperDropIndicator
      className={`${cls}-drop-indicator`}
      $backgroundColor={bgColor}
      $canDrop={canDrop}
      ref={drop}
    >
      {props.children}
    </WrapperDropIndicator>
  );
}
